package com.wuhunyu.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.wxpay.sdk.WXPayUtil;
import com.wuhunyu.commonutils.check.Check;
import com.wuhunyu.commonutils.result.CommonResult;
import com.wuhunyu.constant.WeChatConstant;
import com.wuhunyu.entities.Order;
import com.wuhunyu.entities.PayLog;
import com.wuhunyu.mapper.OrderMapper;
import com.wuhunyu.mapper.PayLogMapper;
import com.wuhunyu.service.PayLogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wuhunyu.servicebase.exception.Assert;
import com.wuhunyu.utils.HttpClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 支付日志表 服务实现类
 * </p>
 *
 * @author wuhunyu
 * @since 2021-01-26
 */
@Service("payLogService")
public class PayLogServiceImpl extends ServiceImpl<PayLogMapper, PayLog> implements PayLogService {

    @Resource
    private PayLogMapper payLogMapper;

    @Resource
    private OrderMapper orderMapper;

    @Override
    public CommonResult generateCode(String orderNo) {
        // 校验参数
        Assert.isRight(Check.isBlank(orderNo), "订单id不能为空");
        // 获取订单详情信息
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_no", orderNo);
        List<Order> orders = orderMapper.selectList(queryWrapper);
        Assert.isRight(orders == null || orders.size() == 0, "查询订单信息失败");
        // 构造map存放微信配置参数
        //1、设置支付参数
        Map<String, String> map = new HashMap<>(16);
        map.put("appid", WeChatConstant.APP_ID);
        map.put("mch_id", WeChatConstant.PARTNER);
        map.put("nonce_str", WXPayUtil.generateNonceStr());
        map.put("body", orders.get(0).getCourseTitle());
        map.put("out_trade_no", orderNo);
        map.put("total_fee", orders.get(0).getTotalFee().multiply(new BigDecimal("100")).longValue()+"");
        map.put("spbill_create_ip", "127.0.0.1");
        map.put("notify_url", WeChatConstant.NOTIFY_URL);
        map.put("trade_type", "NATIVE");
        System.out.println(map.get("appid"));
        System.out.println(map.get("mch_id"));
        // HTTPClient来根据URL访问第三方接口并且传递参数
        HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
        // client设置参数
        Map<String, String> resultMap = null;
        try {
            client.setXmlParam(WXPayUtil.generateSignedXml(map, WeChatConstant.PARTNER_KEY));
            // 支持https协议
            client.setHttps(true);
            client.post();
            //3、返回第三方的数据
            String xml = client.getContent();
            resultMap = WXPayUtil.xmlToMap(xml);
            System.out.println("resultMap=" + resultMap);
        } catch (Exception e) {
            Assert.isRight(true, "请求微信支付二维码失败");
        }
        // 封装返回结果集
        HashMap<String, Object> hashMap = new HashMap<>(16);
        hashMap.put("orderNo", orderNo);
        hashMap.put("courseId", orders.get(0).getCourseId());
        hashMap.put("totalFee", orders.get(0).getTotalFee());
        hashMap.put("resultCode", resultMap.get("result_code"));
        hashMap.put("codeUrl", resultMap.get("code_url"));
        return CommonResult.success("获取微信二维码成功", hashMap);
    }

    @Override
    public Map<String, String> queryPayStatus(String orderNo) {
        // 校验参数
        Assert.isRight(Check.isBlank(orderNo), "订单id不能为空");
        // 查询是否存在该订单
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_no", orderNo);
        List<Order> orders = orderMapper.selectList(queryWrapper);
        Assert.isRight(orders == null || orders.size() == 0, "订单信息不存在");
        // 已支付
        if (orders.get(0).getStatus() == 1) {
            Map<String, String> map = new HashMap<String, String>(16);
            map.put("status", "1");
            return map;
        }
        // 封装参数
        Map<String, String> map = new HashMap<>(16);
        map.put("appid", WeChatConstant.APP_ID);
        map.put("mch_id", WeChatConstant.PARTNER);
        map.put("out_trade_no", orderNo);
        map.put("nonce_str", WXPayUtil.generateNonceStr());
        // 设置请求
        HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
        Map<String, String> resultMap = null;
        try {
            client.setXmlParam(WXPayUtil.generateSignedXml(map, WeChatConstant.PARTNER_KEY));
            client.setHttps(true);
            client.post();
            // 返回第三方的数据
            String xml = client.getContent();
            resultMap = WXPayUtil.xmlToMap(xml);
        } catch (Exception e) {
            Assert.isRight(true, "获取微信支付状态失败");
        }
        return resultMap;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePayStatus(Map<String, String> map) {
        // 校验参数
        Assert.isRight(Check.isBlank(map.get("out_trade_no")), "订单id不能为空");
        // 查询订单是否存在
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_no", map.get("out_trade_no"));
        // 执行查询操作
        List<Order> orders = orderMapper.selectList(queryWrapper);
        Assert.isRight(!(orders != null && orders.size() == 1), "订单不存在");
        // 修改订单状态
        // 订单支付状态，0为未支付，1为已支付
        orders.get(0).setStatus(1);
        // 避免修改创建时间
        orders.get(0).setGmtCreate(null);
        Assert.isRight(orderMapper.updateById(orders.get(0)) != 1, "修改订单支付状态失败");
        // 将支付信息写入数据库中
        PayLog payLog = new PayLog(
                null,
                orders.get(0).getOrderNo(),
                new Date(),
                orders.get(0).getTotalFee(),
                map.get("transaction_id"),
                map.get("trade_state"),
                1,
                JSONObject.toJSONString(map),
                0,
                null,
                null
        );
        // 执行插入操作
        Assert.isRight(payLogMapper.insert(payLog) != 1, "日志写入失败");
    }
}
